import React from 'react';
import './index.scss';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import classnames from 'classnames';
import * as _ from 'lodash';
let head_img = require('./xx.jpeg');
let durex_img = require('./durex.jpeg');
let man = require('./man.jpg');
let woman = require('./woman.jpg');
class Index extends React.Component {
  constructor() {
    super();
    this.state = {
      tr_num: 10,
      td_num: 10,
      td_width: 50,
      td_height: 50,
      direction: '',
      speed: '',
      snake_body: [],
      food: {x: '', y: ''},
      map: []
    };
    const snake = undefined;
  }
  componentWillMount() {
    // create map
    this.createMap();
    // init snake
    this.initSnake();
  }
  componentDidMount() {
    let { snake_body } = this.state;
    this.snake = setInterval(this.move.bind(this), this.state.speed);
    // create food
    this.createFood(snake_body);
    // left: 37, top: 38, right: 39, bottom: 40
    window.document.body.addEventListener('keydown', (e) => {
      let { direction } = this.state;
      let keyCode = e.keyCode;
      if (direction == 37 && (keyCode == 39 || keyCode == 37)) {
        return false;
      } else if (direction == 38 && (keyCode == 38 || keyCode == 40)) {
        return false;
      } else if (direction == 39 && (keyCode == 39 || keyCode == 37)) {
        return false;
      } else if (direction == 40 && (keyCode == 40 || keyCode == 38)) {
        return false;
      }
      switch (e.keyCode) {
        case 38:
          if (direction != 38 || direction != 40) {
            this.changeDirection(e.keyCode);
          }
          break;
        case 37:
          if (direction != 37 || direction != 39) {
            this.changeDirection(e.keyCode);
          }
          break;
        case 40:
          if (direction != 38 || direction != 40) {
            this.changeDirection(e.keyCode);
          }
          break;
        case 39:
          if (direction != 37 || direction != 39) {
            this.changeDirection(e.keyCode);
          }
        default:
          break;
      }
    });
    // set map style
    this.setMapStyle(this.refs.map);
  }
  // set map style
  setMapStyle(map_dom) {
    let { tr_num, td_num, td_width, td_height } = this.state;
    let width = 0, height = 0, marginLeft = 0, marginTop = 0, top = 0, left = 0;
    width = `${td_num * (td_width + 2)}px`;
    height = `${tr_num * (td_height + 2)}px`;
    marginLeft = `-${parseInt(width) / 2}px`;
    marginTop = `20px`;
    top = '50%';
    left = '50%';
    map_dom.style.width = width;
    map_dom.style.height = height;
    map_dom.style.marginLeft = marginLeft;
    map_dom.style.marginTop = marginTop;
    map_dom.style.left = left;
    map_dom.style.top = top;
    console.log(width, height, marginLeft, marginTop, top, left);
  }
  // create map
  createMap() {
    let { map, tr_num, td_num } = this.state;

    for(let i = 0; i < tr_num; i ++) {
      for(let j = 0; j < td_num; j ++) {
        map.push({x: i, y: j});
      }
    }
    this.setState({map: map});
  }
  // init snake
  initSnake() {
    let { snake_body } = this.state;
    snake_body.push({ x: 5, y: 5 });
    snake_body.push({ x: 5, y: 4 });
    snake_body.push({ x: 5, y: 3 });
    this.setState({ snake_body: snake_body, direction: 39, speed: 200 });
  }
  // create food
  createFood(snake_body) {
    let { tr_num, td_num, map, food } = this.state;
    let other = [];
    snake_body.forEach((a, i) => {
      map.forEach((b, j) => {
        if (!_.isEqual(a, b)) {
          other.push(b);
        }
      });
    });
    let target_index_in_other = this.getRandomNumber(0, other.length);
    food.x = other[target_index_in_other].x;
    food.y = other[target_index_in_other].y;
    this.setState({ food: food });
  }
  // if eat food
  ifEatFood(snake_head, food, direction) {
    switch(direction) {
      case 37:
        return snake_head.y - 1 == food.y && snake_head.x == food.x;
      case 38:
        return snake_head.x - 1 == food.x && snake_head.y == food.y;
      case 39:
        return snake_head.y + 1 == food.y && snake_head.x == food.x;
      case 40:
        return snake_head.x + 1 == food.x && snake_head.y == food.y;
      default:
        return false;
    }
  }
  // eat food
  eatFood(snake_body, food) {
    snake_body.unshift(_.cloneDeep(food));
    this.setState({ snake_body: snake_body });
  }
  // get random number
  getRandomNumber(start_number, end_number) {
    let c = end_number - start_number + 1;
    return Math.floor(Math.random() * c + start_number);
  }
  render_map(width, height) {
    let w = [];
    let h = [];
    let map = [];
    for (let i = 0; i < width; i++) {
      w.push(i);
    }
    for (let i = 0; i < height; i++) {
      h.push(i);
    }
    return <div className="map" ref="map">
      {
        w.map((a, i) =>
          <div key={i} className="map-tr">
            {
              h.map((b, j) =>
                <div key={j} className="map-td" className={classnames({
                  "map-td": true,
                  "selected": this.isSnakeBody(i, j) || this.isFood(i, j) ? true : false
                })} style={{ width: this.state.td_width, height: this.state.td_height }}>
                  <img className="snake-img" src={woman} style={{display: this.isSnakeHead({x: i, y: j}) ? 'block' : 'none'}} width={this.state.td_width} height={this.state.td_height} alt=""/>
                  <img className="snake-img" src={man} style={{display: this.isFood(i, j) ? 'block' : 'none'}} alt="" width={this.state.td_width} height={this.state.td_height}/>
                </div>
              )
            }
          </div>
        )
      }
    </div>;
  }
  // is snake head ?
  isSnakeHead(position) {
    let { snake_body } = this.state;
    if (_.isEqual(snake_body[0], position)) {
      return true;
    } else {
      return false;
    }
  }
  // is food
  isFood(x, y) {
    let { food } = this.state;
    if (food.x == x && food.y == y) {
      return true;
    } else {
      return false;
    }
  }
  // is snake body 
  isSnakeBody(x, y) {
    let status = false;
    let { snake_body } = this.state;
    snake_body.forEach((a) => {
      if (a.x === x && a.y === y) {
        status = true;
      }
    });
    return status;
  }

  // auto move the snake
  move() {
    let { direction, snake_body, food } = this.state;
    let snake_body_copy = _.cloneDeep(snake_body);
    switch (direction) {
      case 38:
        if (this.ifAlive(direction, snake_body[0].x) && !this.meetSelf(snake_body[0], snake_body)) {
          if ( this.ifEatFood(snake_body[0], food, direction) ) {
            this.eatFood(snake_body, food);
            this.createFood(snake_body);
          } else {
            snake_body.forEach((a, i) => {
            if (i == 0) {
              a.x -= 1;
            } else {
              a.y = snake_body_copy[i - 1].y;
              a.x = snake_body_copy[i - 1].x;
            }
          });
          this.setState({ snake_body: snake_body });
          }
          
        } else {
          this.stopSnake();
        }

        break;
      case 37:
        if (this.ifAlive(direction, snake_body[0].y) && !this.meetSelf(snake_body[0], snake_body)) {
          if ( this.ifEatFood(snake_body[0], food, direction) ) {
            this.eatFood(snake_body, food);
            this.createFood(snake_body);
          } else {
            snake_body.forEach((a, i) => {
            if (i == 0) {
              a.y -= 1;
            } else {
              a.y = snake_body_copy[i - 1].y;
              a.x = snake_body_copy[i - 1].x;
            }
          });
          this.setState({ snake_body: snake_body });
          }
          
        } else {
          this.stopSnake();
        }

        break;
      case 40:

        if (this.ifAlive(direction, snake_body[0].x) && !this.meetSelf(snake_body[0], snake_body)) {
          if ( this.ifEatFood(snake_body[0], food, direction) ) {
            this.eatFood(snake_body, food);
            this.createFood(snake_body);
          } else {
            snake_body.forEach((a, i) => {
            if (i == 0) {
              a.x += 1;
            } else {
              a.y = snake_body_copy[i - 1].y;
              a.x = snake_body_copy[i - 1].x;
            }
          });
          this.setState({ snake_body: snake_body });
          }
          
        } else {
          this.stopSnake();
        }

        break;
      case 39:
        if (this.ifAlive(direction, snake_body[0].y) && !this.meetSelf(snake_body[0], snake_body)) {
          if ( this.ifEatFood(snake_body[0], food, direction) ) {
            this.eatFood(snake_body, food);
            this.createFood(snake_body);
          } else {
            snake_body.forEach((a, i) => {
            if (i == 0) {
              a.y += 1;
            } else {
              a.y = snake_body_copy[i - 1].y;
              a.x = snake_body_copy[i - 1].x;
            }
          });
          this.setState({ snake_body: snake_body });  
          }
          
        } else {
          this.stopSnake();
        }

        break;

      default:
        break;
    }
  }

  // change the direction
  changeDirection(direction) {
    this.setState({ direction: direction });
  }

  // if the snake alive
  ifAlive(direction, x) {
    switch (direction) {
      case 37:
        if (x == 0) {
          return false;
        } else {
          return true;
        }
      case 38:
        if (x == 0) {
          return false;
        } else {
          return true;
        }
      case 39:
        if (x == this.state.tr_num - 1) {
          return false;
        } else {
          return true;
        }
      case 40:
        if (x == this.state.td_num - 1) {
          return false;
        } else {
          return true;
        }
      default:
        break;
    }
  }

  // 是否碰到自己
  meetSelf(snake_head, snake_body) {
    let status = false;
    snake_body.forEach((a, i) => {
      if (i !=0 && snake_body[i].x == snake_head.x && snake_body[i].y == snake_head.y) {
        status = true;
      }
    });
    return status;
  }

  // stop
  stopSnake() {
    alert('snake was death !');
    clearInterval(this.snake);
    setTimeout(() => {
      window.location.reload();
    }, 500);
  }

  render() {
    return this.render_map(this.state.tr_num, this.state.td_num);
  }
}

let map_state_to_props = (state) => ({});
let map_dispatch_to_props = (dispatch) => (new bindActionCreators({}, dispatch));
let snake = connect(map_state_to_props, map_dispatch_to_props)(Index);
export default snake;